[PATCH] suggested proxy connect patch

I have a patch which I created to simulate users on slow or asymmetric
connections. This patch adds two configuration settings to change the
speed of upload or download thru a tunnelling (CONNECT) proxy.

It's a bit rough, but I wanted to get a general feel about it before I
do much more work refining it. If people think it's useful, I'll do
whatever work is needed to make it clean enough to include in
mod_proxy. Or somebody else can take the basic idea and do it a
better way; whatever you think is best.

In a nutshell, I replace send and recv in proxy_connect.c to calculate
a delay between reading chunks of data. It's very much an
approximation, it doesn't simulate byte-by-byte throughput.

One big problem I know is that it uses usleep(), which I don't think is
available on win32, and maybe not even all unix variants.

Anyway, here's the patch, I welcome any comments or feedback. It's
off 1.3.22, but I don't think these files have changed much since then.

Thanks,

billo
Intuit, Inc. billo [at] billo.com bill_odonnell [at] intuit.com


--- /u/billo/src/apache_1.3.22/src/modules/proxy/mod_proxy.h 2001-10-05 04:19:15.000000000 -0400
+++ ./mod_proxy.h 2002-05-15 18:31:48.201857000 -0400
[at] [at] -224,6 +224,10 [at] [at]
char viaopt_set;
size_t recv_buffer_size;
char recv_buffer_size_set;
+ int throttle_up_speed; /* billo dial-up simulator */
+ char throttle_up_set; /* billo dial-up simulator */
+ int throttle_down_speed; /* billo dial-up simulator */
+ char throttle_down_set; /* billo dial-up simulator */
} proxy_server_conf;

struct hdr_entry {

--- /u/billo/src/apache_1.3.22/src/modules/proxy/proxy_connect.c 2001-10-05 04:19:15.000000000 -0400
+++ ./proxy_connect.c 2002-05-15 18:37:24.476203000 -0400
[at] [at] -96,6 +96,46 [at] [at]
* FIXME: no check for r->assbackwards, whatever that is.
*/

+static useconds_t sleep_calc(int speed, int len)
+{
+ useconds_t delay;
+ if (speed == 0) {
+ return 0;
+ }
+ delay = 1000000 / (speed / 8);
+
+ delay = delay * len;
+
+ return delay;
+}
+
+static ssize_t proxy_recv(int s, void *buf, size_t len, int flags, int choke, request_rec *r)
+{
+ if (choke > 0) {
+ ssize_t ret = recv(s, buf, len, flags);
+ useconds_t delay = sleep_calc(choke, ret);
+ /* ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: billo proxy recv delay %d", delay); */
+ usleep(delay);
+ return ret;
+ } else {
+ return recv(s, buf, len, flags);
+ }
+}
+
+static ssize_t proxy_send(int s, void *buf, size_t len, int flags, int choke, request_rec *r)
+{
+ /* ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: billo proxy send"); */
+ if (choke > 0) {
+ ssize_t ret = send(s, buf, len, flags);
+ useconds_t delay = sleep_calc(choke, ret);
+ usleep(delay);
+ return ret;
+ } else {
+ return send(s, buf, len, flags);
+ }
+}
+
+
static int
allowed_port(proxy_server_conf *conf, int port)
{
[at] [at] -109,6 +149,7 [at] [at]
return 0;
}

+#define CONNECT_BUFFER_SIZE 256

int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
const char *proxyhost, int proxyport)
[at] [at] -119,8 +160,10 [at] [at]
const char *host, *err;
char *p;
int port, sock;
- char buffer[HUGE_STRING_LEN];
+ char buffer[CONNECT_BUFFER_SIZE];
int nbytes, i, j;
+ int throttle_up = 0;
+ int throttle_down = 0;
fd_set fds;

void *sconf = r->server->module_config;
[at] [at] -128,6 +171,12 [at] [at]
(proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;

+ if (conf->throttle_up_set) {
+ throttle_up = conf->throttle_up_speed;
+ }
+ if (conf->throttle_down_set) {
+ throttle_down = conf->throttle_down_speed;
+ }
memset(&server, '\0', sizeof(server));
server.sin_family = AF_INET;

[at] [at] -260,10 +309,10 [at] [at]
if (i) {
if (FD_ISSET(sock, &fds)) {
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "sock was set");
- if ((nbytes = recv(sock, buffer, HUGE_STRING_LEN,0)) != 0) {
+ if ((nbytes = proxy_recv(sock, buffer, CONNECT_BUFFER_SIZE, 0, throttle_down, r)) != 0) {
if (nbytes == -1)
break;
- if (send(ap_bfileno(r->connection->client, B_WR), buffer, nbytes,0) == EOF)
+ if (proxy_send(ap_bfileno(r->connection->client, B_WR), buffer, nbytes,0, throttle_down, r) == EOF)
break;
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Wrote %d bytes to client", nbytes);
}
[at] [at] -272,11 +321,11 [at] [at]
}
else if (FD_ISSET(ap_bfileno(r->connection->client, B_WR), &fds)) {
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "client->fd was set");
- if ((nbytes = recv(ap_bfileno(r->connection->client, B_WR), buffer,
- HUGE_STRING_LEN, 0)) != 0) {
+ if ((nbytes = proxy_recv(ap_bfileno(r->connection->client, B_WR), buffer,
+ CONNECT_BUFFER_SIZE, 0, throttle_up, r)) != 0) {
if (nbytes == -1)
break;
- if (send(sock, buffer, nbytes, 0) == EOF)
+ if (proxy_send(sock, buffer, nbytes, 0, throttle_up, r) == EOF)
break;
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "Wrote %d bytes to server", nbytes);
}
[at] [at] -294,3 +343,4 [at] [at]

return OK;
}
+
--- /u/billo/src/apache_1.3.22/src/modules/proxy/mod_proxy.c 2001-09-24 16:14:27.000000000 -0400
+++ ./mod_proxy.c 2002-05-17 10:45:04.454437000 -0400
[at] [at] -442,6 +507,10 [at] [at]
ps->cache.dirlength_set = 0;
ps->cache.cache_completion = DEFAULT_CACHE_COMPLETION;
ps->cache.cache_completion_set = 0;
+ ps->throttle_up_speed = 0; /* default no choke billo 10-may-2002 */
+ ps->throttle_up_set = 0; /* default no choke billo 10-may-2002 */
+ ps->throttle_down_speed = 0; /* default no choke billo 10-may-2002 */
+ ps->throttle_down_set = 0; /* default no choke billo 10-may-2002 */

return ps;
}
[at] [at] -842,6 +917,31 [at] [at]
return NULL;
}

+
+static const char *
+ set_throttle_up_speed(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ int s = atoi(arg);
+
+ psf->throttle_up_speed = s;
+ psf->throttle_up_set = 1;
+ return NULL;
+}
+
+static const char *
+ set_throttle_down_speed(cmd_parms *parms, void *dummy, char *arg)
+{
+ proxy_server_conf *psf =
+ ap_get_module_config(parms->server->module_config, &proxy_module);
+ int s = atoi(arg);
+
+ psf->throttle_down_speed = s;
+ psf->throttle_down_set = 1;
+ return NULL;
+}
+
static const char*
set_cache_completion(cmd_parms *parms, void *dummy, char *arg)
{
[at] [at] -903,6 +1003,10 [at] [at]
"A list of names, hosts or domains to which the proxy will not connect"},
{"ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF, TAKE1,
"Receive buffer size for outgoing HTTP and FTP connections in bytes"},
+ {"ProxyConnectThrottleUp", set_throttle_up_speed, NULL, RSRC_CONF, TAKE1,
+ "Reduce throughput of connect proxy (upload direction)"},
+ {"ProxyConnectThrottleDown", set_throttle_down_speed, NULL, RSRC_CONF, TAKE1,
+ "Reduce throughput of connect proxy (download direction)"},
{"NoProxy", set_proxy_dirconn, NULL, RSRC_CONF, ITERATE,
"A list of domains, hosts, or subnets to which the proxy will connect directly"},
{"ProxyDomain", set_proxy_domain, NULL, RSRC_CONF, TAKE1,
billo [ Fr, 17 Mai 2002 17:27 ] [ ID #11973 ]

Re: [PATCH] suggested proxy connect patch

Bill O'Donnell wrote:

> I have a patch which I created to simulate users on slow or asymmetric
> connections. This patch adds two configuration settings to change the
> speed of upload or download thru a tunnelling (CONNECT) proxy.

This is really useful functionality, however I don't think it's a good
idea to add it to proxy - as it means you can only use it with the
proxy.

A better idea would be to implement it as a filter, which will allow it
to be used anywhere in Apache. I do notice you implemented it in the
CONNECT part of the proxy - was there a reason for this? The CONNECT
part is one of the last bits that never used filters.

Regards,
Graham
--
-----------------------------------------
minfrin [at] sharp.fm "There's a moon
over Bourbon Street
tonight..."
Graham Leggett [ Sa, 18 Mai 2002 11:53 ] [ ID #11975 ]

Re: [PATCH] suggested proxy connect patch

So, if I added this as a filter, I still *could* use it with proxy,
right?

I did it in the CONNECT part because wanted a generalized byte tunnel
that would throttle down connection speeds for any protocol, HTTP +
SSL usually, but also it could be used for telnet, ssh, whatever. I
also have a dedicated program to do this, but being able to configure
the security (connect) proxy makes the setup process transparent to
the user.

I'll look into filters, and see if I could get them to work with
CONNECT as well.

Thanks for the feedback.

-bill

From: Graham Leggett <minfrin [at] sharp.fm>
Date: Sat, 18 May 2002 11:53:52 +0200

Bill O'Donnell wrote:

> I have a patch which I created to simulate users on slow or asymmetric
> connections. This patch adds two configuration settings to change the
> speed of upload or download thru a tunnelling (CONNECT) proxy.

This is really useful functionality, however I don't think it's a good
idea to add it to proxy - as it means you can only use it with the
proxy.

A better idea would be to implement it as a filter, which will allow it
to be used anywhere in Apache. I do notice you implemented it in the
CONNECT part of the proxy - was there a reason for this? The CONNECT
part is one of the last bits that never used filters.

Regards,
Graham
--
-----------------------------------------
minfrin [at] sharp.fm "There's a moon
over Bourbon Street
tonight..."
billo [ So, 19 Mai 2002 03:23 ] [ ID #11977 ]

Re: [PATCH] suggested proxy connect patch

Bill O'Donnell wrote:

> So, if I added this as a filter, I still *could* use it with proxy,
> right?

Yes, in FTP, HTTP and HTTPS, but not CONNECT (yet).

> I did it in the CONNECT part because wanted a generalized byte tunnel
> that would throttle down connection speeds for any protocol, HTTP +
> SSL usually, but also it could be used for telnet, ssh, whatever. I
> also have a dedicated program to do this, but being able to configure
> the security (connect) proxy makes the setup process transparent to
> the user.

Keep in mind there is no security on the CONNECT part of the proxy - the
only restriction you can apply is to which port you will allow the
client to connect to.

Other than that, I can see how it would be useful for the other
protocols too.

Regards,
Graham
--
-----------------------------------------
minfrin [at] sharp.fm "There's a moon
over Bourbon Street
tonight..."
Graham Leggett [ Mi, 22 Mai 2002 20:08 ] [ ID #11983 ]
Webserver » gmane.comp.apache.mod-proxy » [PATCH] suggested proxy connect patch

Vorheriges Thema: [STATUS] (httpd-proxy) Wed May 22 23:45:18 EDT 2002
Nächstes Thema: httpd-2.0 nightly build log